package com.almm.s_utils;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.omg.CORBA.portable.ApplicationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import reactor.netty.http.client.HttpClient;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import reactor.netty.http.client.HttpClientConfig;
import java.net.Socket;
import java.net.InetSocketAddress;
import java.util.stream.Collectors;

public class Main {

    private static final Logger log = LoggerFactory.getLogger(Main.class);

    /*public static void main(String[] args) {
        // 构造请求 JSON
        JSONObject body = new JSONObject();
        body.put("name", "b"); // b 会触发慢接口

        // 配置 Netty HttpClient 的读超时
        HttpClient httpClient = HttpClient.create()
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000) // 3次握手时间 10秒
                .doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(10, TimeUnit.SECONDS))); // 读取响应时间

        // 创建 WebClient
        WebClient webClient = WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).build();

        try {
                    // Mono<JSONObject> mono = webClient
                    Mono<JSONObject> mono = WebClient.create()
                    .method(HttpMethod.POST)
                    .uri("http://localhost:8080/demo/test")
                    .contentType(MediaType.APPLICATION_JSON)
                    .acceptCharset(StandardCharsets.UTF_8)
                    .bodyValue(body)
                    .retrieve()
                    .bodyToMono(JSONObject.class)
                    .timeout(Duration.ofMinutes(60));
            // 这里阻塞等待结果
            JSONObject result = mono.block(); // 超过 5 秒会报 Netty ReadTimeoutException
            System.out.println("结果: " + JSONObject.toJSONString(result));
        } catch (Exception e) {
            log.error("发生异常:{}", e.getMessage(),e);
        }
    }*/

    public static void main(String[] args) {

    }






    public static   String generateWithRandom() {
        Random random = new Random();
        int number = random.nextInt(900000) + 100000;
        return String.valueOf(number);
    }

    /**
     * 发票冲红
     * @param businessNo 原业务流水号
     */
    public static void writeOffElecBill(String businessNo){
        Map<String, Object> map = new HashMap<>();
        map.put("business_no", businessNo);
        String bn = generateBusinessNo();
        map.put("scarlet_business_no",bn);
        map.put("secret_key",generateSecretKey(bn));
        map.put("create_user_code", "admin");
        map.put("create_user_name", "admin");
        map.put("invoice_agency_code", "202020");
        map.put("scarlet_remark", "门诊退费");
        map.put("ticket_date", "20220716");
        map.put("ticket_time", "08:50:08");
        JSONObject jsonObject = new JSONObject(map);
        String url = "http://192.168.18.200:8585/bsw-server/invoice/sysTicketInfo/writeOffTicketBySN";
        JSONObject request = sendElecBillRequest(jsonObject, url);
        System.err.println(JSONObject.toJSONString(request));
    }


    public static JSONObject sendElecBillRequest(JSONObject jsonBody, String url) {
        String jsonStr = sendHttpWebClient(JSONObject.toJSONString(jsonBody), url);
        return JSONObject.parseObject(jsonStr);
    }

    /**
     * 生成打印业务流水号和key
     * @throws Exception 异常
     */
    public static void generateSecretKeyBusinessNo() throws Exception {
        String business_no = generateBusinessNo();
        String secret_key = generateSecretKey(business_no);
        System.out.println("business_no:"+business_no);
        System.out.println("secret_key:"+secret_key);
    }


    /**
     * 通用调取三方接口
     * @param jsonBody 请求body
     * @param url 请求路径
     * @return 三方接口返回结果
     */
    private static String sendHttpWebClient(String jsonBody,String url) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(java.util.Collections.singletonList(MediaType.APPLICATION_JSON));
        HttpEntity<String> requestEntity = new HttpEntity<>(jsonBody, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);
        return response.getBody();
    }


    /**
     * 生成随机6位数字字符串
     * @return 6位数字字符串
     */
    public static String generateRandomDigitsNoZeroStart() {
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        sb.append(random.nextInt(9) + 1);
        for (int i = 1; i < 6; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }


    /**
     * 生成业务流水号
     * @return 业务流水号
     */
    public static String generateBusinessNo(){
        String orgCode = "202020";
        String yyyyMMddStr = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String randomStr = generateRandomDigitsNoZeroStart();
        return orgCode+yyyyMMddStr + randomStr;
    }

    public static String generateSecretKey(String businessNo) {
        String key = "2BAF467C83413D3954DE657ADD46AF977CEACB3D49AEC301F1B6E0D9C932F750"+businessNo;
        try {
            return getSecretKey(key,"MD5");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 生成密钥
     * @param str key
     * @param type MD5
     * @return 密钥
     * @throws Exception 异常
     */
    public static String getSecretKey(String str, String type) throws Exception {
        if (str != null) {
            MessageDigest md = MessageDigest.getInstance(type.toUpperCase());
            byte[] results = md.digest(str.getBytes());
            String resultString = byteArrayToHexString(results);
            return resultString.toUpperCase();
        } else {
            return null;
        }
    }


    public static String byteArrayToHexString(byte[] b) {
        StringBuffer sb = new StringBuffer(b.length * 2);
        for (int i = 0; i < b.length; i++) {
            int v = b[i] & 0xff;
            if (v < 16) {
                sb.append('0');
            }
            sb.append(Integer.toHexString(v));
        }
        return sb.toString();
    }
}
